﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary
{
    /// <summary>
    /// This class provides the realization of a discrete cosine transform.
    /// </summary>
    [Serializable]
    public class DiscreteCosineTransform
    {
        /// <summary>
        /// The data to transform.
        /// </summary>
        private GeneralVector data;

        /// <summary>
        /// Initializes a new instance of the <see cref="DiscreteCosineTransform"/> class.
        /// </summary>
        /// <param name="data">The data to transform.</param>
        public DiscreteCosineTransform(GeneralVector data)
        {
            if (data == (GeneralVector) null)
            {
                throw new ArgumentNullException("data");
            }

            this.data = data.Copy();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DiscreteCosineTransform"/> class.
        /// </summary>
        /// <param name="data">The data to transform.</param>
        public DiscreteCosineTransform(double[] data)
        {
            if (data == (double[]) null)
            {
                throw new ArgumentNullException("data");
            }

            this.data = new GeneralVector((double[]) data.Clone());
        }

        /// <summary>
        /// Gets or sets the data for the transformation.
        /// </summary>
        /// <value>The data for the transformation.</value>
        public GeneralVector Data
        {
            get { return data; }
            set { data = value; }
        }

        /// <summary>
        /// Transforms the specified data with a discrete cosine transform.
        /// </summary>
        /// <returns>The transformed data.</returns>
        public double[] Transform()
        {
            double omega = Math.PI / this.data.Count;
            double[] result = new double[this.data.Count];

            for (int n = 0; n < this.data.Count; n++)
            {
                result[n] = this.data[n] * Math.Cos(omega * (n + 0.5) * n);
            }

            return result;
        }
    }
}